import L, { LatLng } from 'leaflet';

import Layer from './layer';
import Feature from '../feature/feature';
import Polygon from '../feature/polygon';
import { FeatureJson, LayerOption } from '../types';
import { generateId, getAnotation } from '../util/util';
import { isEqualLatlng } from '../geo/math';

class PolygonsLayer extends Layer {
    /**
     *正在绘制的要素
     */
    private drawingId?: string;

    constructor(layerOption: LayerOption) {
        super(layerOption, 'polygon');
        this.layerOption.drawEnd = this.drawEnd.bind(this);
        this.layerOption.featureClick = this.featureClick.bind(this);
        this.layerOption.featureMousemove = this.featureMousemove.bind(this);
        this.layerOption.featureMouseup = this.featureMouseup.bind(this);
        this.layerOption.addVertex = this.layerOption.nodesLayer!.addVertex.bind(this.layerOption.nodesLayer);
        this.layerOption.getCrossPoint = this.getCrossPoint.bind(this);
    }

    draw(latLng: LatLng) {
        let polygon = this.drawingId ? <Polygon>this.features.get(this.drawingId) : undefined;
        if (!polygon) {
            const id = generateId('polygon');
            this.drawingId = id;
            polygon = new Polygon(id, this.layerOption, [[latLng]], {});
            this.add(polygon);
            polygon.drawStart();
            this.layerOption.mode.setDrawFeature(polygon);
            return;
        } else {
            polygon.addLatLng(latLng);
            this.layerOption.mode.setDrawFeature(polygon);
            if (polygon.latLngs[0].length > 2) {
                // 至少三个点时，再保存到history
                this.layerOption.addHistory({
                    annotation: getAnotation('draw ', polygon),
                    features: [polygon],
                });
            }
        }
    }

    drawMove(latLng: LatLng) {
        if (!this.drawingId) {
            return;
        }
        const polygon = <Polygon>this.features.get(this.drawingId);
        if (polygon) {
            polygon.drawMove(latLng);
        }
    }

    drawEnd(feature: Feature) {
        this.drawingId = undefined;
        this.layerOption.changeMode('select', feature);
        this.layerOption.mode.setDrawFeature(null);
        this.layerOption.eventBus.emit('drawend', feature.instance());
    }

    render(features: FeatureJson[]): Feature[] {
        const results: Feature[] = [];
        features.forEach((item) => {
            item.latLngs = <LatLng[][]>item.latLngs;
            const { id, latLngs, properties } = item;
            // TODO
            if (!latLngs || !latLngs[0] || latLngs[0].length < 3 || this.features.get(id)) {
                return;
            }
            // TODO MultiPolygon时判断首尾的方法不对
            if (
                this.layerOption.mode.drawFeature?.id !== id &&
                !isEqualLatlng(latLngs[0][0], latLngs[0][latLngs[0].length - 1])
            ) {
                // 如果不是绘制中，且没有首尾相连，强制首尾相连
                latLngs[0].push(latLngs[0][0]);
            }
            const polygon = new Polygon(id, this.layerOption, latLngs, {}, properties);
            this.add(polygon);
            results.push(polygon);
            this.renderVertexs(polygon);

            if (this.layerOption.mode.drawFeature?.id === id) {
                // 属于绘制中的要素
                polygon.ajustDashLine();
            }
        });
        return results;
    }

    renderVertexs(polygon: Polygon) {
        polygon.latLngs.forEach((latLngsItem, arrIndex) => {
            latLngsItem.forEach((latLng, index) => {
                if (
                    index === latLngsItem.length - 1 &&
                    isEqualLatlng(latLngsItem[0], latLngsItem[latLngsItem.length - 1])
                ) {
                    // 如果首尾相等，最后一个坐标不用渲染
                    return;
                }
                const judgeRepeat = true;
                const show = false;
                const vertexId = this.layerOption.nodesLayer?.addVirtualVertex(
                    latLng,
                    [polygon],
                    { className: 'vertex' },
                    judgeRepeat
                );
                // const vertexId = this.layerOption.nodesLayer!.addVertex(
                //     latLng,
                //     [polygon],
                //     { className: 'vertex' },
                //     judgeRepeat,
                //     show
                // );
                if (vertexId) {
                    if (!polygon.relateNodeIds[arrIndex]) {
                        polygon.relateNodeIds[arrIndex] = [];
                    }
                    polygon.relateNodeIds[arrIndex].push(vertexId);
                }
            });
        });
    }
}

export default PolygonsLayer;
